#include "llib_version.h"
#define L_VERSION   1111225
#if L_VERSION == LLIB_VERSION_TO_TEST

#include <boost/test/unit_test.hpp>
#include <boost/mpl/list.hpp>
using namespace boost;

#include <llib.h>
using namespace llib;

BOOST_AUTO_TEST_SUITE(Vector_test_suite)

typedef mpl::list<Int8, Int16, Int32, Int64, Uint8, Uint16, Uint32, Uint64, Float, Double, Boolean>     all_types;
typedef mpl::list<Int8, Int16, Int32, Int64, Uint8, Uint16, Uint32, Uint64, Float, Double>              all_num_types;
typedef mpl::list<Int8, Int16, Int32, Int64, Uint8, Uint16, Uint32, Uint64>                             int_types;
typedef mpl::list<Int8, Int16, Int32, Int64>                                                            signed_int_types;
typedef mpl::list<Uint8, Uint16, Uint32, Uint64>                                                        unsigned_int_types;
typedef mpl::list<Float, Double>                                                                        float_point_types;

BOOST_AUTO_TEST_CASE(vector_declaration)
{
    BOOST_CHECK_EQUAL( sizeof(Vec<Int32,1>), 4 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Int32,2>), 8 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Int32,3>), 12 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Int32,4>), 16 );

    BOOST_CHECK_EQUAL( sizeof(Vec<Uint32,1>), 4 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Uint32,2>), 8 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Uint32,3>), 12 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Uint32,4>), 16 );

    BOOST_CHECK_EQUAL( sizeof(Vec<Int16,1>), 2 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Int16,2>), 4 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Int16,3>), 6 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Int16,4>), 8 );

    BOOST_CHECK_EQUAL( sizeof(Vec<Uint16,1>), 2 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Uint16,2>), 4 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Uint16,3>), 6 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Uint16,4>), 8 );

    BOOST_CHECK_EQUAL( sizeof(Vec<Int8,1>), 1 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Int8,2>), 2 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Int8,3>), 3 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Int8,4>), 4 );

    BOOST_CHECK_EQUAL( sizeof(Vec<Uint8,1>), 1 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Uint8,2>), 2 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Uint8,3>), 3 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Uint8,4>), 4 );

    BOOST_CHECK_EQUAL( sizeof(Vec<Float,1>), 4 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Float,2>), 8 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Float,3>), 12 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Float,4>), 16 );

    BOOST_CHECK_EQUAL( sizeof(Vec<Double,1>), 8 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Double,2>), 16 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Double,3>), 24 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Double,4>), 32 );

    BOOST_CHECK_EQUAL( sizeof(Vec<Boolean,1>), 1 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Boolean,2>), 2 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Boolean,3>), 3 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Boolean,4>), 4 );

    BOOST_CHECK_EQUAL( sizeof(Vec<Char,1>), 1 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Char,2>), 2 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Char,3>), 3 );
    BOOST_CHECK_EQUAL( sizeof(Vec<Char,4>), 4 );
}

BOOST_AUTO_TEST_CASE_TEMPLATE(vector_declaration_template, T, all_types)
{
    BOOST_CHECK_EQUAL( sizeof(Vec<T,1>), sizeof(T) * 1 );
    BOOST_CHECK_EQUAL( sizeof(Vec<T,2>), sizeof(T) * 2 );
    BOOST_CHECK_EQUAL( sizeof(Vec<T,3>), sizeof(T) * 3 );
    BOOST_CHECK_EQUAL( sizeof(Vec<T,4>), sizeof(T) * 4 );
    BOOST_CHECK_EQUAL( sizeof(Vec<T,6>), sizeof(T) * 6 );
    BOOST_CHECK_EQUAL( sizeof(Vec<T,10>), sizeof(T) * 10 );
}

BOOST_AUTO_TEST_CASE(vector_constructor)
{
    Vec<Int32,1> v_I32_1;
    BOOST_CHECK_EQUAL( v_I32_1[0], 0 );

    Vec<Boolean,2> v_B_2;
    BOOST_CHECK_EQUAL( v_B_2[0], FALSE );
    BOOST_CHECK_EQUAL( v_B_2[1], FALSE );
    v_B_2 = Vec<Boolean,2>(TRUE, FALSE);
    BOOST_CHECK_EQUAL( v_B_2[0], TRUE );
    BOOST_CHECK_EQUAL( v_B_2[1], FALSE );

    Vec<Int64,2> v_I64_2(5345,2342);
    BOOST_CHECK_NE( v_I64_2[0], v_I64_2[1] );

    Vec<Uint16,3> v_U16_3;
    BOOST_CHECK_EQUAL( v_U16_3[0], 0 );
    BOOST_CHECK_EQUAL( v_U16_3[1], 0 );
    BOOST_CHECK_EQUAL( v_U16_3[2], 0 );
    v_U16_3 = Vec<Uint16,3>(1,2,3);
    BOOST_CHECK_EQUAL( v_U16_3[0], 1 );
    BOOST_CHECK_EQUAL( v_U16_3[1], 2 );
    BOOST_CHECK_EQUAL( v_U16_3[2], 3 );

    Vec<Double,4> v_D_4;
    BOOST_CHECK_EQUAL( v_D_4[0], 0.0 );
    BOOST_CHECK_EQUAL( v_D_4[1], 0.0 );
    BOOST_CHECK_EQUAL( v_D_4[2], 0.0 );
    BOOST_CHECK_EQUAL( v_D_4[3], 0.0 );

}

BOOST_AUTO_TEST_CASE_TEMPLATE(vecotr_operation_equal, T, all_num_types)
{
    Vec<T,1> v11, v12;
    BOOST_CHECK_EQUAL( v11, v12 );
    v11[0] += 1;
    BOOST_CHECK_NE( v11, v12 );

    Vec<T,2> v21, v22;
    BOOST_CHECK_EQUAL( v21, v22 );
    v21[1] += 2;
    BOOST_CHECK_NE( v21, v22 );

    Vec<T,3> v31, v32;
    BOOST_CHECK_EQUAL( v31, v32 );
    v31[2] += 3;
    BOOST_CHECK_NE( v31, v32 );

    Vec<T,4> v41, v42;
    BOOST_CHECK_EQUAL( v41, v42 );
    v41[3] += 4;
    BOOST_CHECK_NE( v41, v42 );

    Vec<T,5> v51, v52;
    BOOST_CHECK_EQUAL( v51, v52 );
    v51[4] += 5;
    BOOST_CHECK_NE( v51, v52 );
}

BOOST_AUTO_TEST_CASE(vector_operation_bool)
{
    Vec<Boolean,1> b11, b12;
    BOOST_CHECK_EQUAL(b11, b12);
    b11[0] = TRUE;
    b12[0] = FALSE;
    BOOST_CHECK_NE(b11, b12);
    b11[0] = TRUE;
    b12[0] = TRUE;
    BOOST_CHECK_EQUAL(b11, b12);

    Vec<Boolean,3> b31, b32;
    BOOST_CHECK_EQUAL(b31, b32);
    b31[0] = TRUE;
    b32[0] = FALSE;
    BOOST_CHECK_NE(b31, b32);
    b31[0] = b32[0] = TRUE;
    b31[1] = b32[1] = FALSE;
    b31[2] = TRUE;
    b32[2] = FALSE;
    BOOST_CHECK_NE(b31, b32);
    b31[2] = TRUE;
    b32[2] = TRUE;
    BOOST_CHECK_EQUAL(b31, b32);
}

BOOST_AUTO_TEST_CASE_TEMPLATE(vector_operation_compare, T, all_num_types)
{
    Vec<T,1> v11, v12;
    BOOST_CHECK_EQUAL( v11, v12 );
    v11[0] += 1;
    BOOST_CHECK_GT( v11, v12 );

    Vec<T,2> v21, v22;
    BOOST_CHECK_EQUAL( v21, v22 );
    v21[1] += 1;
    BOOST_CHECK_GT( v21, v22 );

    Vec<T,3> v31, v32;
    BOOST_CHECK_EQUAL( v31, v32 );
    v31[2] += 1;
    BOOST_CHECK_GT( v31, v32 );

    Vec<T,4> v41, v42;
    BOOST_CHECK_EQUAL( v41, v42 );
    v41[3] += 1;
    BOOST_CHECK_GT( v41, v42 );

    Vec<T,5> v51, v52;
    BOOST_CHECK_EQUAL( v51, v52 );
    v51[4] += 1;
    BOOST_CHECK_GT( v51, v52 );
}

BOOST_AUTO_TEST_CASE_TEMPLATE(vector_operation_arithmetic, T, signed_int_types)
{
    Vec<T,1> v11;
    v11[0] = 1;
    Vec<T,1> v12 = -v11;
    BOOST_CHECK_GT( v11, v12 );

    Vec<T,2> v21;
    v21[1] = 1;
    Vec<T,2> v22 = -v21;
    BOOST_CHECK_GT( v21, v22 );

    Vec<T,3> v31;
    v31[2] = 1;
    Vec<T,3> v32 = -v31;
    BOOST_CHECK_GT( v31, v32 );

    Vec<T,4> v41;
    v41[3] = 1;
    Vec<T,4> v42 = -v41;
    BOOST_CHECK_GT( v41, v42 );
}


BOOST_AUTO_TEST_SUITE_END()

#endif
